package ru.amse.stroganova;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.UnsupportedLookAndFeelException;

import ru.amse.stroganova.ui.GraphComponent;
import ru.amse.stroganova.ui.action.AlgorythmMessageListener;
import ru.amse.stroganova.ui.action.FileActionsFactory;
import ru.amse.stroganova.ui.action.ToggleAction;

/**
 * Main Window for Graph Editor application.
 * 
 * @author Dasha Strogaova
 * 
 */
public class MainWindow extends JFrame {

	private final static String ABOUT_MESSAGE = "<html><p align=center><h3>Graph Editor</h3><br> "
			+ "Version 1.0, Freeware, 10.05.2007<br><br>"
			+ "<hr>This program is designed for creating and editing different graph types.<br>"
			+ "Graphs can be loaded and saved.<br>You can undo or redo up to 10 most recent actions.<br>"
			+ "There several graph algorythms that can be executed on your graph.<br><hr><br> "
			+ "Author: Daria Stroganova (<a href=\"mailto:dasha_str@mail.ru\">dasha_str@mail.ru</a>)<br> "
			+ "Designed for: Academy of Modern Software Engineering</p></html>";

	private final GraphComponent graphComponent;

	private final ArrayList<ToggleAction> modeActions;

	private final JLabel messageBar;

	private final FileActionsFactory fileActionsFactory;

	private final AlgorythmMessageListener algorythmMessageListener = new AlgorythmMessageListener() {

		public void messageRecieved(String message, boolean isError) {
			messageBar.setText(message);
			if (isError) {
				messageBar.setForeground(Color.RED);
			} else {
				messageBar.setForeground(Color.DARK_GRAY);
			}
			mainComponent.add(messageBar, BorderLayout.NORTH);
			messageBar.setVisible(true);
			mainComponent.revalidate();
			mainComponent.repaint();
		}

		public void messageUnactive() {
			mainComponent.remove(messageBar);
			mainComponent.revalidate();
			mainComponent.repaint();
		}

	};

	private final JComponent mainComponent;

	/**
	 * Constructs main window.
	 * 
	 * @throws UnsupportedLookAndFeelException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws ClassNotFoundException
	 * 
	 */
	public MainWindow() {
		super("Graph Editor");
		setIconImage(new ImageIcon(ClassLoader
				.getSystemResource("img/icon.gif")).getImage());
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		setLayout(new BorderLayout());

		graphComponent = new GraphComponent();
		graphComponent.getAlgorythmActionsFactory().addAlgorythmErrorListener(
				algorythmMessageListener);
		JScrollPane scrollPane = new JScrollPane(graphComponent);

		fileActionsFactory = new FileActionsFactory(this, graphComponent);
		modeActions = new ArrayList<ToggleAction>();
		createModeActions();

		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				fileActionsFactory.getExitAction().actionPerformed(null);
			}
		});

		messageBar = new JLabel();
		makeMessageBar();

		mainComponent = new JComponent() {
		};
		mainComponent.setLayout(new BorderLayout());
		mainComponent.add(scrollPane, BorderLayout.CENTER);

		setJMenuBar(createMainMenu());
		getContentPane().add(createToolbar(), BorderLayout.NORTH);
		getContentPane().add(mainComponent, BorderLayout.CENTER);

		setSize(500, 450);
		setLocation(300, 150);
		setVisible(true);
	}

	private void createModeActions() {
		modeActions.add(graphComponent.getEditingActionsFactory()
				.getSelectAction());
		modeActions.add(graphComponent.getEditingActionsFactory()
				.getAddVertexAction());
		modeActions.add(graphComponent.getEditingActionsFactory()
				.getAddEdgeAction());
		// modeActions.add(graphComponent.getAlgorythmActionsFactory().getAlgorythmAction());
		graphComponent.getEditingActionsFactory().getAddEdgeAction()
				.setEnabled(false);
		graphComponent.getEditingActionsFactory().getAddVertexAction()
				.setEnabled(false);
		graphComponent.getEditingActionsFactory().getSelectAction().setEnabled(
				false);

	}

	private JToolBar createToolbar() {
		JToolBar toolBar = new JToolBar();
		ButtonGroup group = new ButtonGroup();
		JToggleButton button;
		for (ToggleAction action : modeActions) {
			button = new JToggleButton(action);
			button.setText("");
			group.add(button);
			action.addButton(button);
			toolBar.add(button);
		}
		toolBar.addSeparator();

		toolBar
				.add(graphComponent.getEditingActionsFactory()
						.getDeleteAction());
		toolBar.add(graphComponent.getEditingActionsFactory()
				.getCircleLayoutAction());
		toolBar.addSeparator();
		toolBar.add(graphComponent.getEditingActionsFactory()
				.getDiscardHighlightingAction());
		toolBar.setVisible(true);
		return toolBar;
	}

	private JMenuBar createMainMenu() {
		JMenuBar mainMenu = new JMenuBar();
		mainMenu.add(createFileMenu());
		mainMenu.add(createEditMenu());
		mainMenu.add(createAlgorythmsMenu());
		mainMenu.add(createConvertionMenu());
		mainMenu.add(createHelpMenu());
		return mainMenu;
	}

	private JMenu createFileMenu() {
		JMenu fileMenu = new JMenu("File");
		fileMenu.add(fileActionsFactory.getNewAction());
		fileMenu.add(fileActionsFactory.getOpenAction());
		fileMenu.addSeparator();
		fileMenu.add(fileActionsFactory.getSaveAction());
		fileMenu.add(fileActionsFactory.getSaveAsAction());
		fileMenu.addSeparator();
		fileMenu.add(fileActionsFactory.getExitAction());
		return fileMenu;
	}

	private JMenu createEditMenu() {
		JMenu editMenu = new JMenu("Edit");
		editMenu.add(graphComponent.getEditingActionsFactory().getUndoAction());
		editMenu.add(graphComponent.getEditingActionsFactory().getRedoAction());
		editMenu.addSeparator();
		ButtonGroup group = new ButtonGroup();
		JRadioButtonMenuItem item;
		for (ToggleAction action : modeActions) {
			item = new JRadioButtonMenuItem(action);
			group.add(item);
			action.addButton(item);
			editMenu.add(item);
		}
		editMenu.addSeparator();
		editMenu.add(graphComponent.getEditingActionsFactory()
				.getDeleteAction());
		editMenu.add(graphComponent.getEditingActionsFactory()
				.getCircleLayoutAction());
		editMenu.addSeparator();
		editMenu.add(graphComponent.getEditingActionsFactory()
				.getDiscardHighlightingAction());
		return editMenu;
	}

	private JMenu createAlgorythmsMenu() {
		JMenu algorythmMenu = new JMenu("Algorythms");
		algorythmMenu.add(graphComponent.getAlgorythmActionsFactory()
				.getTopSortAction());
		algorythmMenu.add(graphComponent.getAlgorythmActionsFactory()
				.getMinSpanningTreeAction());
		algorythmMenu.add(graphComponent.getAlgorythmActionsFactory()
				.getDijkstraTreeAction());
		algorythmMenu.add(graphComponent.getAlgorythmActionsFactory()
				.getMaxFlowAction());
		return algorythmMenu;
	}

	private JMenu createConvertionMenu() {
		JMenu convertionMenu = new JMenu("Convert");
		convertionMenu.add(graphComponent.getConvertionActionsFactory()
				.getToWeightedAction());
		convertionMenu.add(graphComponent.getConvertionActionsFactory()
				.getToUnweightedAction());
		convertionMenu.add(graphComponent.getConvertionActionsFactory()
				.getToUndirectedAction());
		return convertionMenu;
	}

	private JMenu createHelpMenu() {
		JMenu helpMenu = new JMenu("Help");
		helpMenu.add(new AbstractAction("About") {
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(MainWindow.this,
						MainWindow.ABOUT_MESSAGE, "About",
						JOptionPane.QUESTION_MESSAGE);
			}
		});
		return helpMenu;
	}

	private void makeMessageBar() {
		messageBar.setBorder(BorderFactory.createRaisedBevelBorder());
		messageBar.setVerticalAlignment(JLabel.CENTER);
		messageBar.setHorizontalAlignment(JLabel.CENTER);
		messageBar.setBackground(new Color(255, 253, 232));
		messageBar.setOpaque(true);
		messageBar.setFont(new Font("Arial", Font.ITALIC, 13));
	}
}
